package com.iteaj.iot.test.server.dtu;

import com.iteaj.iot.CoreConst;
import com.iteaj.iot.consts.ExecStatus;
import com.iteaj.iot.server.dtu.impl.CommonDtuProtocol;
import com.iteaj.iot.server.dtu.impl.CommonDtuServerComponent;
import com.iteaj.iot.test.IotTestHandle;
import com.iteaj.iot.test.TestConst;
import com.iteaj.iot.test.simulator.DtuSimulatorTestHandle;
import com.iteaj.iot.utils.ByteUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;

@Component
@ConditionalOnExpression("${iot.test.dtu-start:false} and ${iot.test.server:false}")
public class DtuTestHandle implements IotTestHandle {

    @Autowired(required = false)
    private CommonDtuServerComponent serverComponent;
    private Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void start() throws Exception {
        System.out.println("-------------------------------------- Dtu 通用服务测试 ----------------------------------------------");
        serverComponent.getDeviceManager().forEach(item -> {
            Object deviceSn = item.attr(CoreConst.EQUIP_CODE).get();
            if(deviceSn instanceof String) {
                // 异步写测试
                CommonDtuProtocol protocol = new CommonDtuProtocol((String) deviceSn);
                protocol.writeOfAsync("write test of async".getBytes(StandardCharsets.UTF_8));
                if(protocol.getExecStatus() == ExecStatus.success) {
                    logger.info(TestConst.LOGGER_PROTOCOL_DESC, serverComponent.getName(), "DTU异步写", deviceSn, null, "通过");
                } else {
                    logger.error(TestConst.LOGGER_PROTOCOL_DESC, serverComponent.getName(), "DTU异步写", deviceSn, null, "失败("+protocol.getExecStatus()+")");
                }

                /**
                 * 同步写测试必须包含 sync 字符串, DtuSimulatorTestHandle才会返回 OK
                 */
                CommonDtuProtocol syncProtocol = new CommonDtuProtocol((String) deviceSn);
                byte[] write = syncProtocol.write("write test of sync".getBytes(StandardCharsets.UTF_8));
                if(syncProtocol.getExecStatus() == ExecStatus.success) {
                    if(new String(write).equals("OK")) {
                        logger.info(TestConst.LOGGER_PROTOCOL_DESC, serverComponent.getName(), "DTU同步写", deviceSn, null, "通过");
                    } else {
                        logger.error(TestConst.LOGGER_PROTOCOL_DESC, serverComponent.getName(), "DTU同步写", deviceSn, null, "失败(响应数据错误)");
                    }
                } else {
                    logger.error(TestConst.LOGGER_PROTOCOL_DESC, serverComponent.getName(), "DTU同步写", deviceSn, null, "失败("+syncProtocol.getExecStatus()+")");
                }

                /**
                 * 读测试必须包含 read 字符串, DtuSimulatorTestHandle才会返回 相同的字符串
                 * @see DtuSimulatorTestHandle#start()
                 */
                String writeStr = "read test of sync 10s";
                CommonDtuProtocol timeout = new CommonDtuProtocol((String) deviceSn).timeout(10000);
                byte[] read = timeout.read(writeStr.getBytes(StandardCharsets.UTF_8));
                if(timeout.getExecStatus() == ExecStatus.success) {
                    String respMsg = new String(read);
                    if(respMsg.equals(writeStr)) {
                        logger.info(TestConst.LOGGER_PROTOCOL_DESC, serverComponent.getName(), "DTU同步读取", deviceSn, null, "通过");
                    } else {
                        logger.error(TestConst.LOGGER_PROTOCOL_DESC, serverComponent.getName(), "DTU同步读取", deviceSn, null, "失败(数据不一致)");
                    }
                } else {
                    logger.error(TestConst.LOGGER_PROTOCOL_DESC, serverComponent.getName(), "DTU同步读取", deviceSn, null, "失败("+timeout.getExecStatus()+")");
                }
            }
        });
    }

    @Override
    public int getOrder() {
        return 5000;
    }
}
